package io.github.wanggit.antrpc.commons.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

@Slf4j
public abstract class JsonUtils {

    private JsonUtils() {
        throw new IllegalStateException();
    }

    public static String toJsonString(Object obj) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            if (log.isErrorEnabled()) {
                log.error("toJson error.", e);
            }
            throw new JsonRuntimeException(e);
        }
    }

    public static String toJsonString(Object obj, boolean throwEx) {
        try {
            return toJsonString(obj);
        } catch (Exception e) {
            if (throwEx) {
                throw e;
            }
            return null;
        }
    }

    public static String toJsonPrettyString(Object obj) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            if (log.isErrorEnabled()) {
                log.error("toJson error.", e);
            }
            throw new JsonRuntimeException(e);
        }
    }

    public static byte[] toJsonBytes(Object obj) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            if (log.isErrorEnabled()) {
                log.error("toJson error.", e);
            }
            throw new JsonRuntimeException(e);
        }
    }

    public static <T> T fromJson(byte[] data, Class<T> tClass) {
        if (null == data || data.length == 0) {
            return null;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(data, tClass);
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("from json error.", e);
            }
            throw new JsonRuntimeException(e);
        }
    }

    public static <T> T fromJson(String json, Class<T> tClass) {
        return internalFromJson(json, tClass);
    }

    private static <T> T internalFromJson(String json, Object javaType) {
        if (!StringUtils.hasText(json)) {
            return null;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            //noinspection unchecked
            return objectMapper.readValue(json, (Class<T>) javaType);
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("from json error.", e);
            }
            throw new JsonRuntimeException(e);
        }
        /*return null;*/
    }

    public static class JsonRuntimeException extends RuntimeException {
        private static final long serialVersionUID = 5978030762568666164L;

        public JsonRuntimeException(Throwable cause) {
            super(cause);
        }
    }
}
